#ifndef WIDGETS_H_
#define WIDGETS_H_

#include <gtkmm.h>

#include "log.h"
#include "conf.h"
#include "keybind.h"
#include "search.h"

#include "gtkversion.h"

namespace gpyp {

class Application;

template<typename T>
class DialogWrapper : public boost::shared_ptr<T> {
private:
  sigc::signal<void, int> signal_response_;
public:
  inline sigc::signal<void, int> signal_response() {
    return signal_response_;
  }

private:
  sigc::connection conn_response_;

  void dialog_on_response(int response_id) {
    signal_response_(response_id);
    if (response_id != Gtk::RESPONSE_APPLY) reset();
  }

  const DialogWrapper<T> &operator=(const DialogWrapper<T> &wrap);

public:
  void reset() {
    conn_response_.disconnect();
    boost::shared_ptr<T>::reset();
  }
  void reset(T *ptr) {
    conn_response_.disconnect();
    boost::shared_ptr<T>::reset(ptr);
    conn_response_ = ptr->signal_response()
      .connect(sigc::mem_fun(*this, &DialogWrapper<T>::dialog_on_response));
  }

  DialogWrapper() {
  }
  ~DialogWrapper() {
    conn_response_.disconnect();
  }
private:
  DialogWrapper(const DialogWrapper<T> &wrap);
};

class TextMenuBase : boost::noncopyable {
private:
  Application &app_;

protected:
  virtual void prepare_commandopts(CommandOpts &opts);

  void create_menu(Gtk::Menu *menu);

  TextMenuBase(Application &app);
  virtual ~TextMenuBase();
};

template<typename T>
class TextMenu : public TextMenuBase,
                 public T {
protected:
  virtual void on_populate_popup(Gtk::Menu *menu) {
    create_menu(menu);
  }

  TextMenu(Application &app) :
    TextMenuBase(app)
  {
  }
};

class Entry : public TextMenu<Gtk::Entry> {
private:
  Glib::ustring text_;

protected:
  virtual void prepare_commandopts(CommandOpts &opts);

public:
  Entry(Application &app);
};

class EntryLabel : public Entry {
private:
  sigc::connection conn_parent_style_changed_;

protected:
  virtual void on_realize();
  virtual void on_parent_changed(Gtk::Widget *previous_parent);

private:
  void parent_on_style_changed(const Glib::RefPtr<Gtk::Style> &previous_style);

  void update_color();

public:
  EntryLabel(Application &app);
  virtual ~EntryLabel();
};

class Label : public TextMenu<Gtk::Label> {
private:
  Glib::ustring text_;

protected:
  virtual void prepare_commandopts(CommandOpts &opts);

public:
  Label(Application &app, const Glib::ustring &label = Glib::ustring());
};

class TextView : public TextMenu<Gtk::TextView> {
private:
  Application  &app_;
  Glib::ustring text_;

  Glib::RefPtr<Gtk::TextTag> tag_search_;

protected:
  virtual void prepare_commandopts(CommandOpts &opts);

  virtual void on_changed();

  void set_monospace_font();

  void clear_search();

public:
  void search(RefRegex re);

  TextView(Application  &app,
           bool          monospace = false,
           Gtk::WrapMode wrap = Gtk::WRAP_CHAR);
};

class HostEntry : public Gtk::Entry {
private:
  RefAttributeHost attr_;
  sigc::connection conn_attr_changed_;

protected:
  void attr_on_changed();

public:
  void set(RefAttributeHost attr);

  HostEntry(RefAttributeHost attr);
  virtual ~HostEntry();
};

class TreeView : public Gtk::TreeView {
public:
  static PangoWrapMode DEFAULT_TOOLTIP_WRAP_MODE;

private:
  class Tooltip : public Gtk::Widget {
    friend class TreeView;
  public:
    static const int MIN_WIDTH;

  private:
    Application                 &app_;
    Gtk::TreeView               &treeview_;
    ConfMain::RefTooltip         conf_;

    PangoWrapMode                wrap_mode_;
    uint                         xpad_;
    uint                         ypad_;

    GtkCellRendererText         *renderer_;
    PangoEllipsizeMode           save_ellipsize_;
    gboolean                     save_ellipsize_set_;
    PangoWrapMode                save_wrap_mode_;
    gint                         save_wrap_width_;
    guint                        save_xpad_;
    guint                        save_ypad_;
    Gtk::TreeViewColumn         *tree_view_column_;
    Glib::RefPtr<Gtk::TreeModel> tree_model_;
    Gtk::TreeIter                tree_iter_;
    bool                         is_expander_;
    bool                         is_expanded_;

    GdkRectangle                 background_area_;
    GdkRectangle                 cell_area_;

    Gtk::TreePath                last_path_;
    Gtk::TreeViewColumn         *last_column_;

    Gtk::TreeIter                selected_iter_;

  protected:
    virtual void on_realize();
    virtual void on_unrealize();
    virtual bool on_expose_event(GdkEventExpose *event);

  public:
    void set(GtkCellRendererText         *renderer,
             PangoEllipsizeMode           save_ellipsize,
             gboolean                     save_ellipsize_set,
             PangoWrapMode                save_wrap_mode,
             gint                         save_wrap_width,
             guint                        save_xpad,
             guint                        save_ypad,
             Gtk::TreeViewColumn         *tree_view_column,
             Glib::RefPtr<Gtk::TreeModel> tree_model,
             Gtk::TreeIter               &tree_iter,
             bool                         is_expander,
             bool                         is_expanded);
    void set_background_area(int x, int y, int w, int h);
    void set_cell_area(int x, int y, int w, int h);

    inline void clear_last() {
      last_column_ = NULL;
      last_path_.clear();
    }

    inline void size_allocate(GdkRectangle &rect) {
      GtkWidget *w = gobj();
      GTK_WIDGET_GET_CLASS(w)->size_allocate(w, &rect);
    }

    inline void show() {
      GtkWidget *w = gobj();
      GTK_WIDGET_GET_CLASS(w)->show(w);
    }
    inline void hide() {
      GtkWidget *w = gobj();
      GTK_WIDGET_GET_CLASS(w)->hide(w);
      tree_model_.clear();
    }

    Tooltip(Application &app, Gtk::TreeView &treeview);
    virtual ~Tooltip();
  };

private:
  double           scroll_hvalue_;
  double           scroll_vvalue_;
  bool             restore_scroll_value_;
  sigc::connection conn_hadj_value_changed_;
  sigc::connection conn_vadj_value_changed_;

  Tooltip    *tooltip_;
  GHashTable *cache_renderer_;

protected:
  virtual bool on_button_press_event(GdkEventButton *event);
  virtual void on_size_allocate(Gtk::Allocation &allocation);

  void hadj_on_changed();
  void hadj_on_value_changed();
  void vadj_on_changed();
  void vadj_on_value_changed();

  virtual void on_set_scroll_adjustments(Gtk::Adjustment *hadjustment,
                                         Gtk::Adjustment *vadjustment);

  void store_scroll_value();

  void update_tooltip_pos(int x, int y);
  void update_tooltip();

#ifndef GTK_CELL_LAYOUT_HAVE_GET_CELLS
  virtual GtkCellRenderer *get_tooltip_renderer(GtkTreeViewColumn *column);
#endif

  virtual void forall_vfunc(gboolean include_internals, GtkCallback callback, gpointer callback_data);
  virtual bool on_motion_notify_event(GdkEventMotion *event);
  virtual bool on_leave_notify_event(GdkEventCrossing *event);
  virtual void on_columns_changed();
  virtual void selection_on_changed();

  inline void hide_tooltip() {
    if (tooltip_) {
      tooltip_->hide();
      tooltip_->clear_last();
    }
  }

  inline void set_tooltip_wrap_mode(PangoWrapMode wrap_mode) {
    if (wrap_mode != tooltip_->wrap_mode_) {
      tooltip_->wrap_mode_ = wrap_mode;
      update_tooltip();
    }
  }

public:
  TreeView();
  TreeView(Application &app, bool enable_tooltip = true);
  virtual ~TreeView();
};

class WidgetInputBase : boost::noncopyable {
public:
  typedef ConfInput::RefInputEntry RefInputEntry;

private:
  Application  &app_;
  RefInputEntry input_;

protected:
  virtual void prepare_commandopts(CommandOpts &opts) = 0;

  virtual bool on_popup(guint button, guint32 activate_time);
  virtual bool on_button_press_event(GdkEventButton *event);
  virtual bool on_key_press_event(GdkEventKey *event);

  bool run(ConfMain::RefCommand comm);

  WidgetInputBase(Application &app, RefInputEntry input);
  virtual ~WidgetInputBase();
};

template<typename W>
class WidgetInput : public WidgetInputBase,
                    public W {
protected:
  inline virtual bool on_button_press_event(GdkEventButton *event) {
    bool res = W::on_button_press_event(event);
    if (WidgetInputBase::on_button_press_event(event)) return true;
    return res;
  }
  inline virtual bool on_key_press_event(GdkEventKey *event) {
    if (WidgetInputBase::on_key_press_event(event)) return true;
    return W::on_key_press_event(event);
  }

  inline WidgetInput(Application             &app,
                     ConfInput::RefInputEntry input) :
    WidgetInputBase(app, input)
  {
    W::add_events(Gdk::KEY_PRESS_MASK);
  }
};
template<> inline
WidgetInput<Entry>::WidgetInput(Application             &app,
                                ConfInput::RefInputEntry input) :
  WidgetInputBase(app, input),
  Entry          (app)
{
}
template<> inline
WidgetInput<TextView>::WidgetInput(Application             &app,
                                   ConfInput::RefInputEntry input) :
  WidgetInputBase(app, input),
  TextView       (app)
{
}

template<>
class WidgetInput<TreeView> : public WidgetInputBase,
                              public TreeView {
public:
  inline virtual bool on_button_press_event(GdkEventButton *event) {
    bool res = TreeView::on_button_press_event(event);
    if (WidgetInputBase::on_button_press_event(event)) return true;
    return res;
  }
  inline virtual bool on_key_press_event(GdkEventKey *event) {
    if (WidgetInputBase::on_key_press_event(event)) return true;
    return TreeView::on_key_press_event(event);
  }

  inline WidgetInput(Application             &app,
                     ConfInput::RefInputEntry input,
                     bool                     enable_tooltip = false) :
    WidgetInputBase(app, input),
    TreeView       (app, enable_tooltip)
  {
    TreeView::add_events(Gdk::KEY_PRESS_MASK);
  }
};

template<typename T>
class TreeModelColumnWrapper : boost::noncopyable {
private:
  Gtk::TreeModelColumn<T> column_;

public:
  inline Gtk::TreeModelColumn<T> &operator*() {
    return column_;
  }

  inline TreeModelColumnWrapper(Gtk::TreeModelColumnRecord &columns) {
    columns.add(column_);
  }
};
template<>
class TreeModelColumnWrapper<void> : boost::noncopyable {
public:
  inline TreeModelColumnWrapper(Gtk::TreeModelColumnRecord &/*columns*/) {
  }
};

template<typename T1, typename T2 = void>
class ListManager : boost::noncopyable {
protected:
  Gtk::TreeModelColumnRecord   columns_;
  TreeModelColumnWrapper<T1>   column1_;
  TreeModelColumnWrapper<T2>   column2_;

  Glib::RefPtr<Gtk::ListStore> liststore_;

public:
  T1 get_item(Gtk::TreeIter iter) {
    if (iter) {
      Gtk::TreeRow row = *iter;
      return row[*column1_];
    } else {
      return T1();
    }
  }
  T1 get_item(Gtk::TreePath path) {
    return get_item(liststore_->get_iter(path));
  }
  T1 get_item(const Glib::ustring &path) {
    return get_item(liststore_->get_iter(path));
  }
  Gtk::TreeIter get_iter(T1 item) {
    Gtk::TreeNodeChildren children = liststore_->children();
    for(Gtk::TreeIter iter = children.begin();
        iter != children.end(); ++iter) {
      if (get_item(iter) == item) {
        return iter;
      }
    }
    return Gtk::TreeIter();
  }

  Gtk::TreeIter add(T1 item) {
    if (!get_iter(item)) {
      Gtk::TreeIter iter = liststore_->append();
      iter->set_value(*column1_, item);
      return iter;
    }
    return Gtk::TreeIter();
  }
  bool remove(const Gtk::TreeIter &iter) {
    if (iter) {
      liststore_->erase(iter);
      return true;
    }
    return false;
  }
  bool remove(T1 item) {
    return remove(get_iter(item));
  }
  bool reorder(T1 item, T1 prev, T1 next) {
    Gtk::TreeIter iter      = get_iter(item);
    Gtk::TreeIter iter_prev = get_iter(prev);
    Gtk::TreeIter iter_next = get_iter(next);
    if (iter) {
      if (iter_next) {
        liststore_->move(iter, iter_next);
      } else {
        liststore_->move(iter, ++iter_prev);
      }
      return true;
    }
    return true;
  }
  void clear() {
    liststore_->clear();
  }

protected:
  ListManager() :
    column1_(columns_),
    column2_(columns_)
  {
    liststore_ = Gtk::ListStore::create(columns_);
  }
  virtual ~ListManager() {
  }
};

template<typename T>
class ListView : public TreeView,
                 public ListManager<typename T::RefItem> {
public:
  typedef boost::shared_ptr<T> RefCollection;
  typedef typename T::RefItem RefItem;

private:
  sigc::signal<void, RefItem> signal_selected_;
public:
  sigc::signal<void, RefItem> signal_selected() {
    return signal_selected_;
  }

private:
  RefCollection    collection_;

  sigc::connection conn_item_added_;
  sigc::connection conn_item_removed_;
  sigc::connection conn_item_reordered_;
  sigc::connection conn_cleared_;

protected:
  void selection_on_changed() {
    signal_selected_(get_selected());
  }

  virtual void collection_on_item_added(RefItem item) {
    Gtk::TreeIter iter = ListManager<RefItem>::add(item);
    if (iter) get_selection()->select(iter);
  }
  virtual void collection_on_item_removed(RefItem item) {
    Gtk::TreeIter iter = get_iter(item);
    if (iter) {
      Glib::RefPtr<Gtk::TreeSelection> selection = get_selection();
      Gtk::TreeIter selected = selection->get_selected();
      if (selected && selected == iter) {
        Gtk::TreeNodeChildren children =
          ListManager<typename T::RefItem>::liststore_->children();
        Gtk::TreeIter iter_sel = iter;
        ++iter_sel;
        if (!iter_sel && iter != children.begin()) {
          iter_sel = iter;
          --iter_sel;
        }
        if (iter_sel) selection->select(iter_sel);
      }
    }
    if (!ListManager<RefItem>::remove(iter)) {
      log::dbg << "bug: ListView::collection_on_item_removed" << log::endl;
    }
  }
  virtual void collection_on_item_reordered(RefItem item,
                                            RefItem prev,
                                            RefItem next) {
    if (!ListManager<RefItem>::reorder(item, prev, next)) {
      log::dbg << "bug: ListView::collection_on_item_reordered" << log::endl;
    }
  }
  virtual void collection_on_cleared() {
    ListManager<RefItem>::clear();
  }

public:
  void up() {
    if (!collection_) return;
    Gtk::TreeIter iter = get_selection()->get_selected();
    RefItem item = ListManager<RefItem>::get_item(iter);
    if (item && iter != ListManager<RefItem>::liststore_->children().begin()) {
      collection_->reorder_item(item, RefItem(), ListManager<RefItem>::get_item(--iter));
    }
  }
  void down() {
    if (!collection_) return;
    Gtk::TreeIter iter = get_selection()->get_selected();
    RefItem item = ListManager<RefItem>::get_item(iter), next;
    if (item && (next = ListManager<RefItem>::get_item(++iter))) {
      collection_->reorder_item(item, next, RefItem());
    }
  }
  void add() {
    if (!collection_) return;
    RefItem selected = get_selected();
    RefItem added = collection_->add_item();
    if (selected && added) {
      collection_->reorder_item(added, RefItem(), selected);
    }
  }
  void remove() {
    if (!collection_) return;
    RefItem item = get_item(get_selection()->get_selected());
    if (item) collection_->remove_item(item);
  }

  void select_first() {
    Gtk::TreeIter iter = ListManager<RefItem>::liststore_->children().begin();
    if (iter) get_selection()->select(iter);
  }
  void select(RefItem item) {
    Gtk::TreeIter iter = ListManager<RefItem>::get_iter(item);
    if (iter) get_selection()->select(iter);
  }

  RefItem get_selected() {
    return get_item(get_selection()->get_selected());
  }

protected:
  virtual void set(RefCollection collection) {
    conn_item_added_    .disconnect();
    conn_item_removed_  .disconnect();
    conn_item_reordered_.disconnect();
    conn_cleared_       .disconnect();

    collection_ = collection;
    collection_on_cleared();

    if (collection_) {
      for(typename T::iterator iter = collection_->begin();
          iter != collection_->end(); ++iter) {
        ListManager<RefItem>::add(*iter);
      }
#define CONN(N)                                                         \
      conn_##N##_ = collection_->signal_##N()                           \
        .connect(sigc::mem_fun(*this, &ListView<T>::collection_on_##N))
      CONN(item_added);
      CONN(item_removed);
      CONN(item_reordered);
      CONN(cleared);
#undef CONN
    }
  }

private:
  void init() {
    set_model(ListManager<RefItem>::liststore_);
    get_selection()->signal_changed()
      .connect(sigc::mem_fun(*this, &ListView<T>::selection_on_changed));
  }

protected:
  ListView() {
    init();
  }
  ListView(RefCollection collection) {
    set(collection);
    init();
  }
  ListView(Application &app, bool enable_tooltip = false) :
    TreeView(app, enable_tooltip)
  {
    init();
  }
  ListView(Application &app, RefCollection collection, bool enable_tooltip = false) :
    TreeView(app, enable_tooltip)
  {
    set(collection);
    init();
  }
public:
  virtual ~ListView() {
    conn_item_added_    .disconnect();
    conn_item_removed_  .disconnect();
    conn_item_reordered_.disconnect();
    conn_cleared_       .disconnect();
  }
};

template<typename T>
class SelectorListView : public ListView<T> {
public:
  typedef typename ListView<T>::RefCollection RefCollection;

private:
  Gtk::CellRendererText renderer_name_;
  Gtk::TreeViewColumn   column_name_;

  void _on_cell_data(Gtk::CellRenderer *cell, const Gtk::TreeIter &iter) {
    on_cell_data(dynamic_cast<Gtk::CellRendererText *>(cell), iter);
  }

protected:
  virtual void on_cell_data(Gtk::CellRendererText *cell, const Gtk::TreeIter &iter) = 0;

private:
  void init() {
    column_name_.set_cell_data_func(renderer_name_, sigc::mem_fun(*this, &SelectorListView::_on_cell_data));
    ListView<T>::append_column(column_name_);
    ListView<T>::set_headers_visible(false);
  }

protected:
  SelectorListView() :
    column_name_("Name", renderer_name_)
  {
    init();
  }
  SelectorListView(RefCollection collection) :
    ListView<T> (collection),
    column_name_("Name", renderer_name_)
  {
    init();
  }
};

template<typename T>
class SelectorComboBox : public Gtk::ComboBox,
                         public ListManager<T, Glib::ustring> {
private:
  typedef ListManager<T, Glib::ustring> Super;

private:
  sigc::signal<void, T> signal_selected_;
public:
  sigc::signal<void, T> signal_selected() {
    return signal_selected_;
  }

private:
  Gtk::CellRendererText renderer_;

protected:
  virtual void on_changed() {
    signal_selected_(get_active());
  }

public:
  Gtk::TreeIter add(T item, const Glib::ustring &name) {
    if (!Super::get_iter(item)) {
      Gtk::TreeIter iter = Super::liststore_->append();
      Gtk::TreeRow  row  = *iter;
      row[*Super::column1_] = item;
      row[*Super::column2_] = name;
      return iter;
    }
    return Gtk::TreeIter();
  }

  inline void set_active(const Gtk::TreeIter &iter) {
    Gtk::ComboBox::set_active(iter);
  }
  inline void set_active(T item) {
    Gtk::TreeIter iter = get_iter(item);
    if (iter) set_active(iter);
  }
  inline T get_active() {
    Gtk::TreeIter iter = Gtk::ComboBox::get_active();
    if (iter) return Super::get_item(iter);
    return T();
  }

private:
  void init() {
    set_model(Super::liststore_);
    pack_start(renderer_);
    add_attribute(renderer_.property_text(), *Super::column2_);
  }

public:
  SelectorComboBox() {
    init();
  }
};

class SearchBox : public Gtk::HBox {
private:
  class TypeButton : public Gtk::MenuToolButton {
  private:
    RefAttributeSearchType search_type_;

    Gtk::Image             icon_;
    Gtk::Menu              menu_;
    Gtk::RadioButtonGroup  rbg_type_;
    Gtk::RadioMenuItem     mi_normal_;
    Gtk::RadioMenuItem     mi_migemo_;
    Gtk::RadioMenuItem     mi_regex_;

    sigc::connection       conn_enable_migemo_changed_;
    sigc::connection       conn_search_type_changed_;

  protected:
    virtual void on_realize();
    virtual void on_clicked();

    void enable_migemo_on_changed();

    void search_type_on_changed();
    void mi_type_on_activate();

  public:
    TypeButton(RefAttributeSearchType search_type);
    virtual ~TypeButton();
  };

public:
  class Entry : public WidgetInput<gpyp::Entry> {
  private:
    SearchBox &box_;

  protected:
    virtual void prepare_commandopts(CommandOpts &opts);
    virtual void on_populate_popup(Gtk::Menu *menu);

  public:
    Entry(Application             &app,
          SearchBox               &box,
          ConfInput::RefInputEntry input);
  };

private:
  Application &app_;
  RefSearch    search_;

  TypeButton   typebutton_;
  Entry        entry_;

  sigc::connection conn_entry_changed_;

protected:
  virtual void prepare_commandopts(CommandOpts &opts);

  virtual void on_show();
  virtual void on_hide();

  void entry_on_changed();

public:
  inline void clear() {
    entry_.set_text(Glib::ustring());
  }

  inline Entry &get_entry() {
    return entry_;
  }

  inline RefSearch get_search() {
    return search_;
  }

  inline void grab_focus() {
    entry_.grab_focus();
  }

  void convert_to_regex();

  SearchBox(Application             &app,
            RefSearch                search,
            ConfInput::RefInputEntry input);
};

class TextEditor : public WidgetInput<Gtk::VBox> {
private:
  TextView            editor_;
  Gtk::ScrolledWindow sw_editor_;
  RefSearch           search_;
  SearchBox           search_box_;

protected:
  virtual void prepare_commandopts(CommandOpts &opts);

  virtual void search_on_changed();
  virtual void search_box_on_hide();

public:
  /* const関数にすると2.16で
     undefined reference to `Gtk::TextBuffer::get_text(bool) const'
     となるので */
  inline Glib::ustring get_text() {
    return editor_.get_buffer()->get_text();
  }
  inline void set_text(const Glib::ustring &text) {
    editor_.get_buffer()->set_text(text);
  }

  TextEditor(Application &app);
};

class TextEditorDialog : public Gtk::Dialog {
private:
  TextEditor editor_;

public:
  inline Glib::ustring get_text() {
    return editor_.get_text();
  }
  inline void set_text(const Glib::ustring &text) {
    editor_.set_text(text);
  }

  TextEditorDialog(Application &app, Gtk::Window &parent);
};

class MessageDialog : public Gtk::MessageDialog {
public:
  inline void set(const Glib::ustring &message) {
    Gtk::MessageDialog::set_secondary_text(message);
  }

  inline void show() {
    Gtk::MessageDialog::show();
  }

protected:
  MessageDialog(Gtk::MessageType     type,
                const Glib::ustring &message1,
                const Glib::ustring &message2);
  MessageDialog(Gtk::Window         &parent,
                Gtk::MessageType     type,
                const Glib::ustring &message1,
                const Glib::ustring &message2);
};

class WarningDialog : public MessageDialog {
public:
  WarningDialog(const Glib::ustring &message = Glib::ustring());
  WarningDialog(Gtk::Window         &parent,
                const Glib::ustring &message = Glib::ustring());
  inline WarningDialog(const Glib::ustring &message1,
                       const Glib::ustring &message2) :
    MessageDialog(Gtk::MESSAGE_WARNING, message1, message2)
  {
  }
  inline WarningDialog(Gtk::Window         &parent,
                       const Glib::ustring &message1,
                       const Glib::ustring &message2) :
    MessageDialog(parent, Gtk::MESSAGE_WARNING, message1, message2)
  {
  }
};

class ErrorDialog : public MessageDialog {
public:
  ErrorDialog(const Glib::ustring &message = Glib::ustring());
  ErrorDialog(Gtk::Window         &parent,
              const Glib::ustring &message = Glib::ustring());
  inline ErrorDialog(const Glib::ustring &message1,
                     const Glib::ustring &message2) :
    MessageDialog(Gtk::MESSAGE_ERROR, message1, message2)
  {
  }
  inline ErrorDialog(Gtk::Window         &parent,
                     const Glib::ustring &message1,
                     const Glib::ustring &message2) :
    MessageDialog(parent, Gtk::MESSAGE_ERROR, message1, message2)
  {
  }
};

}/*gpyp*/

#endif/*WIDGETS_H_*/
